package com.extweb4j.core.model;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.extweb4j.core.kit.ExtKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Table;
import com.jfinal.plugin.activerecord.TableMapping;

/**
 * 核心model,增强jfinal model的操作方法
 * @param <M>
 */
@SuppressWarnings("rawtypes")
public abstract class CoreModel<M extends Model> extends Model<M>{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Table table;
	private String tableName;
	private String primaryKey;
	private String modelName;

	private String selectSql;
	private String fromSql;
	private String updateSql;
	private String deleteSql;
	private String dropSql;
	private String countSql;

	protected static String blank = " ";

	private String getSet(String set) {
		if (set != null && !set.isEmpty()
				&& !set.trim().toUpperCase().startsWith("SET")) {
			set = " SET " + set;
		}
		return set;
	}

	private String getWhere(String where) {
		if (where != null && !where.isEmpty()
				&& !where.trim().toUpperCase().startsWith("WHERE")) {
			where = " WHERE " + where;
		}
		return where;
	}

	@SuppressWarnings("unchecked")
	private Table getTable() {
		 if (table == null) {
		      Class clazz = getClass();
		      table = TableMapping.me().getTable(clazz);
		    }
		    return table;
	}

	private String getPrimaryKey() {
		if (primaryKey == null) {
			primaryKey = getTable().getPrimaryKey()[0];
		}
		return primaryKey;
	}

	private String getTableName() {
		if (tableName == null) {
			tableName = getTable().getName();
		}
		return tableName;
	}

	private String getModelName() {
		if (modelName == null) {
		      Class clazz = getClass();
		      byte[] items = clazz.getSimpleName().getBytes();
		      items[0] = (byte) ((char) items[0] + ('a' - 'A'));
		      modelName = new String(items);
		    }
		    return modelName;
	}

	private String getSelectSql() {
		if (selectSql == null) {
			selectSql = " SELECT " + getModelName() + ".* ";
		}
		return selectSql;
	}

	private String getFromSql() {
		if (fromSql == null) {
			fromSql = " FROM " + getTableName() + " " + getModelName() + " ";
		}
		return fromSql;
	}

	private String getUpdateSql() {
		if (updateSql == null) {
			updateSql = " UPDATE " + getTableName() + " " + getModelName()
					+ " ";
		}
		return updateSql;
	}

	private String getDeleteSql() {
		if (deleteSql == null) {
			deleteSql = " DELETE FROM " + getTableName() +" ";
		}
		return deleteSql;
	}

	private String getDropSql() {
		if (dropSql == null) {
			dropSql = " DELETE FROM " + getTableName() + " ";
		}
		return dropSql;
	}

	private String getCountSql() {
		if (countSql == null) {
			countSql = " SELECT COUNT(*) count FROM " + getTableName() + " "
					+ getModelName() + " ";
		}
		return countSql;
	}
	/**
	 * 根据属性查询一个实体
	 * @param attr
	 * @param value
	 * @return
	 */
	public M findFirstByAttr(Object attr, Object value) {
		return findFirst(getSelectSql() + getFromSql()
				+ getWhere(attr + " = ?"), value);
	}
	/**
	 * 根据属性查询实体列表
	 * @param attr
	 * @param value
	 * @return
	 */
	public List<M> findByAttr(Object attr, Object value) {
		return find(getSelectSql() + getFromSql()
				+ getWhere(attr + " = ?"), value);
	}
	/**
	 * 根据属性查询排除此属性的实体列表
	 * @param attr
	 * @param value
	 * @return
	 */
	public List<M> findByExcludeAttr(Object attr, Object value) {
		return find(getSelectSql() + getFromSql()
				+ getWhere(attr + " != ?"), value);
	}
	/**
	 * 根据where条件查询实体列表
	 * @param where
	 * @param paras
	 * @return
	 */
	public List<M> findBy(String where, Object... paras) {
		return find(getSelectSql() + getFromSql() + getWhere(where),
				paras);
	}
	/**
	 * 根据where条件查询一个实体
	 * @param where
	 * @param paras
	 * @return
	 */
	public M findFirstBy(String where, Object... paras) {
		return findFirst(getSelectSql() + getFromSql() + getWhere(where),
				paras);
	}
	/**
	 * 根据where条件查询前N条数据
	 * @param topNumber
	 * @param where
	 * @param paras
	 * @return
	 */
	public List<M> findTopBy(int topNumber, String where, Object... paras) {
		return paginate(1, topNumber, getSelectSql(),
				getFromSql() + getWhere(where), paras).getList();
	}
	/**
	 * 查询所有数据，慎用
	 * @return
	 */
	public List<M> findAll() {
		return find(getSelectSql() + getFromSql());
	}

	public Page<M> paginateAll(int pageNumber, int pageSize) {
		return paginate(pageNumber, pageSize, getSelectSql(),
				getFromSql());
	}

	public Page<M> paginateBy(int pageNumber, int pageSize, String where,
			Object... paras) {
		return paginate(pageNumber, pageSize, getSelectSql(),
				getFromSql() + getWhere(where), paras);
	}

	public boolean updateAll(String set, Object... paras) {
		return Db.update(getUpdateSql() + getSet(set), paras) > 0;
	}

	public boolean updateBy(String set, String where, Object... paras) {
		return Db.update(getUpdateSql() + getSet(set) + getWhere(where), paras) > 0;
	}

	public boolean deleteAll() {
		return Db.update(getDeleteSql()) > 0;
	}

	public boolean deleteBy(String where, Object... paras) {
		return Db.update(getDeleteSql() + getWhere(where), paras) > 0;
	}
	
	public boolean deleteByAttr(String attr, Object para) {
		return Db.update(getDeleteSql() + getWhere(attr + " = ?"), para) > 0;
	}
	
	public boolean dropAll() {
		return Db.update(getDropSql()) > 0;
	}

	public boolean dropBy(String where, Object... paras) {
		return Db.update(getDropSql() + getWhere(where), paras) > 0;
	}

	public Long countAll() {
		return Db.queryFirst(getCountSql());
	}

	public Long countBy(String where, Object... paras) {
		return Db.queryFirst(getCountSql() + getWhere(where), paras);
	}
	
	 /*****************************************************************************
	   * 
	   * 自定义方法实现
	   * 
	   * 
	   */
	  public Page<M> pageDataBy(int page,int limit,String  search,String sort,String order,String where,Object[] ps) {
		 StringBuffer whereSqlBuff  = new StringBuffer(" WHERE 1=1");
		 List<Object> params = new ArrayList<Object>();
		 if(where!=null){
			 whereSqlBuff.append(" AND ").append(where);
			 if(ps!=null && ps.length > 0){
				 for(Object p : ps){
					 params.add(p);
				 }
			 }
		 }
		 //条件
		 if(StringUtils.isNotBlank(search)){
			 search = ExtKit.sqlFilterValidate(search);
			 Map<String, Class<?>> map = getTable().getColumnTypeMap();
			 Iterator<String> it = map.keySet().iterator();
			 whereSqlBuff.append(" AND (");
			 int t = 0;
			 while(it.hasNext()){
				 String key = it.next();
				 Class clazz = map.get(key);
				 if(clazz.equals(String.class) && !key.equals(getPrimaryKey())){
					 String sql = new StringBuffer(key).append(" LIKE '%"+search+"%' ").toString();
					 whereSqlBuff.append(t==0?sql:" OR "+sql);
					// params.add(search);
					 t++;
				 }
			 }
			 whereSqlBuff.append(")");
		 }
		 //排序
		 if(StringUtils.isNotBlank(sort) && StringUtils.isNotBlank(order)){
			 whereSqlBuff.append(" ORDER BY ").append(sort).append(" ").append(order);
		 }
		 return super.paginate(page, limit,getSelectSql(),getFromSql()+whereSqlBuff.toString(),params.toArray());
	  	}

		public Page<M> pageDataBy(int page,int limit,String search) {
			return pageDataBy( page,limit,search,null,null,null,null);
		}
		public Page<M> pageDataBy(int page,int limit) {
			return pageDataBy( page,limit,null,null,null,null,null);
		}
		public Page<M> pageDataBy(int page,int limit,String search,String sort,String order ) {
			return pageDataBy( page,limit,search,sort,order,null,null);
		}
		
	/**
	 * 根据关键词进行like查询	
	 * @param attr
	 * @param paras
	 * @return
	 */
	public List<M> likeAttr(String attr,String paras){
		paras = ExtKit.sqlFilterValidate(paras);
		return find(getSelectSql() + getFromSql() + getWhere(attr + " LIKE '%"+paras+"%' "));
	}
	
}
